//
//
//

#include "xlispplaintextedit.h"
#include "xlispp.h"
#include <QShortcut>

#include <iostream>

class XlispCBProvider : public xlispqt::XlispEngine::CbProvider {
public:
	void setupCallbacks(xlispqt::XlispEngine *engine) const {
		engine->setConsoleAtBOLPCB(xlispqt::XlispPlainTextEdit::consoleAtBOLP);
		engine->setConsoleCheckCB(xlispqt::XlispPlainTextEdit::consoleCheck);
		engine->setConsoleFlushInputCB(xlispqt::XlispPlainTextEdit::consoleFlushInput);
		engine->setConsoleFlushOutputCB(xlispqt::XlispPlainTextEdit::consoleFlushOutput);
		engine->setConsoleGetCCB(xlispqt::XlispPlainTextEdit::consoleGetC);
		engine->setConsolePutCCB(xlispqt::XlispPlainTextEdit::consolePutC);
		engine->setExitCB(xlispqt::XlispPlainTextEdit::exit);
	}
};


xlispqt::XlispPlainTextEdit *xlispqt::XlispPlainTextEdit::m_instance = 0;

xlispqt::XlispPlainTextEdit::XlispPlainTextEdit(QWidget *parent) : 
	QPlainTextEdit(parent),
	m_last_cursor_position(0),
	m_engine(0)
{
	setup();
}

xlispqt::XlispPlainTextEdit::XlispPlainTextEdit(const QString &text, QWidget *parent) :
	QPlainTextEdit(text, parent),
	m_last_cursor_position(0),
	m_engine(0)
{
	setup();
}

xlispqt::XlispPlainTextEdit::~XlispPlainTextEdit()
{
	delete m_engine;
}

void
xlispqt::XlispPlainTextEdit::init(int argc, char **argv)
{
	XlispCBProvider cbs;
	m_instance = this;
	m_engine = new xlispqt::XlispEngine(argc, argv, &cbs);
	m_last_cursor_position = this->textCursor().position();
}

void 
xlispqt::XlispPlainTextEdit::keyPressEvent(QKeyEvent *e)
{
	parent_t::keyPressEvent(e);
}

void
xlispqt::XlispPlainTextEdit::setup()
{
	bool c;
	c = connect(this, SIGNAL(textChanged()), this, SLOT(textWasChanged())); 
	Q_ASSERT(c);

	QShortcut *ctr_return = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this);
	c = connect(ctr_return, SIGNAL(activated()), this, SLOT(shortcutPressed())); 
	Q_ASSERT(c);

	c = connect(this, SIGNAL(inputReady(QString)), this, SLOT(eval(QString)));
	Q_ASSERT(c);
}

void
xlispqt::XlispPlainTextEdit::textWasChanged()
{
}

void
xlispqt::XlispPlainTextEdit::shortcutPressed()
{
	QString text;
	if(this->textCursor().hasSelection()) {
		QString selected = textCursor().selectedText();
		for(int pos = 0 ; pos < selected.length() ; ++pos)
			text.append(selected.at(pos).toAscii() ? selected.at(pos) : QChar('\n'));
	} else {
		for(int pos = m_last_cursor_position ; pos < textCursor().position() ; ++pos) {
			text.append(document()->characterAt(pos).toAscii() ? document()->characterAt(pos) : QChar('\n'));
		}
	}
	emit inputReady(text);
	m_last_cursor_position = this->textCursor().position();
}

void
xlispqt::XlispPlainTextEdit::eval(QString text)
{
	m_engine->eval(text.toStdString().c_str());
}

void 
xlispqt::XlispPlainTextEdit::consolePutC(int ch)
{
	current_instance()->textCursor().insertText(QChar(ch));
}

int 
xlispqt::XlispPlainTextEdit::consoleGetC(void)
{
	return -1; // EOF
}

void 
xlispqt::XlispPlainTextEdit::consoleFlushOutput(void)
{
}

void 
xlispqt::XlispPlainTextEdit::consoleFlushInput(void)
{
}

int 
xlispqt::XlispPlainTextEdit::consoleCheck(void)
{
	return -1;
}

int 
xlispqt::XlispPlainTextEdit::consoleAtBOLP(void)
{
	return current_instance()->textCursor().atStart();
}

void
xlispqt::XlispPlainTextEdit::exit(int sts)
{
	std::cout << "xlispqt::XlispPlainTextEdit::exit(" << sts << ")" << std::endl;
	emit current_instance()->quitRequest(sts);
}
